#include "fmi2Functions.h"


typedef struct {
    fmi2Integer theOnlyInteger;
    fmi2Real timeStart;
    fmi2Real timeStop;
} ModelInstance;


const char *fmi2GetTypesPlatform()
{
    return fmi2TypesPlatform;
}


const char *fmi2GetVersion()
{
    return "2.0";
}


fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID, fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions, fmi2Boolean visible, fmi2Boolean loggingOn)
{
    puts("fmi2Instantiate()");
    ModelInstance *pModel = (ModelInstance *)malloc(sizeof(ModelInstance));
    pModel->theOnlyInteger = 0;
    pModel->timeStart = 0.0;
    pModel->timeStop = 0.0;
    return pModel;
}


void fmi2FreeInstance(fmi2Component c)
{
    puts("fmi2FreeInstance()");
    free(c);
}


fmi2Status fmi2SetDebugLogging(fmi2Component c, fmi2Boolean loggingOn, size_t nCategories, const fmi2String categories[])
{
    puts("fmi2SetDebugLogging() - unused");
    return fmi2Error;
}


fmi2Status fmi2SetupExperiment(fmi2Component c, fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime)
{
    puts("fmi2SetupExperiment()");
    ModelInstance *pModel = (ModelInstance *)c;
    pModel->timeStart = startTime;
    pModel->timeStop = stopTime;
    return fmi2OK;
}


fmi2Status fmi2EnterInitializationMode(fmi2Component c)
{
    puts("fmi2EnterInitializationMode()");
    return fmi2OK;
}


fmi2Status fmi2ExitInitializationMode(fmi2Component c)
{
    puts("fmi2ExitInitializationMode()");
    return fmi2OK;
}


fmi2Status fmi2Terminate(fmi2Component c)
{
    puts("fmi2Terminate()");
    return fmi2OK;
}


fmi2Status fmi2Reset(fmi2Component c)
{
    puts("fmi2Reset()");
    return fmi2OK;
}


fmi2Status fmi2GetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Real value[])
{
    puts("fmi2GetReal()");
    return fmi2Warning;
}


fmi2Status fmi2GetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[])
{
    puts("fmi2GetInteger()");
    ModelInstance *pModel = (ModelInstance *)c;
    for (int i = 0; i < nvr; i++)
    {
        value[i] = pModel->theOnlyInteger;
    }
    return fmi2OK;
}


fmi2Status fmi2GetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2Boolean value[])
{
    puts("fmi2GetBoolean()");
    return fmi2Warning;
}


fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, fmi2String value[])
{
    puts("fmi2GetString()");
    return fmi2Warning;
}


fmi2Status fmi2SetReal(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Real value[])
{
    puts("fmi2SetReal()");
    return fmi2Warning;
}


fmi2Status fmi2SetInteger(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer value[])
{
    puts("fmi2SetInteger()");
    ModelInstance *pModel = (ModelInstance *)c;
    if (nvr == 0)
    {
        return fmi2Error;
    }
    pModel->theOnlyInteger = value[0];
    return fmi2OK;
}


fmi2Status fmi2SetBoolean(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Boolean value[])
{
    puts("fmi2SetBoolean()");
    return fmi2Warning;
}


fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2String value[])
{
    puts("fmi2SetString()");
    return fmi2Warning;
}


fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate *state)
{
    puts("fmi2GetFMUstate() - unused");
    return fmi2Error;
}


fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate state)
{
    puts("fmi2SetFMUstate() - unused");
    return fmi2Error;
}


fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate *state)
{
    puts("fmi2FreeFMUstate() - unused");
    return fmi2Error;
}


fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate state, size_t *size)
{
    puts("fmi2SerializedFMUstateSize() - unused");
    return fmi2Error;
}


fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate state, fmi2Byte data[], size_t size)
{
    puts("fmi2SerializeFMUstate() - unused");
    return fmi2Error;
}


fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte data[], size_t size, fmi2FMUstate *state)
{
    puts("fmi2DeSerializeFMUstate() - unused");
    return fmi2Error;
}


fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown, const fmi2ValueReference vKnown_ref[], size_t nKnown, const fmi2Real dvKnown[], fmi2Real dvUnknown[])
{
    puts("fmi2GetDirectionalDerivative() - unused");
    return fmi2Error;
}


fmi2Status fmi2SetRealInputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], const fmi2Real value[])
{
    puts("fmi2SetRealInputDerivatives() - unused");
    return fmi2Error;
}


fmi2Status fmi2GetRealOutputDerivatives(fmi2Component c, const fmi2ValueReference vr[], size_t nvr, const fmi2Integer order[], fmi2Real value[])
{
    puts("fmi2GetRealOutputDerivatives() - unused");
    return fmi2Error;
}


fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPoint)
{
    puts("fmi2DoStep()");
    ModelInstance *pModel = (ModelInstance *)c;
    if (currentCommunicationPoint < pModel->timeStart || currentCommunicationPoint > pModel->timeStop)
    {
        return fmi2Error;
    }
    return fmi2OK;
}


fmi2Status fmi2CancelStep(fmi2Component c)
{
    puts("fmi2CancelStep()");
    return fmi2Warning;
}


fmi2Status fmi2GetStatus(fmi2Component c, const fmi2StatusKind s, fmi2Status *value)
{
    puts("fmi2GetStatus() - unused");
    return fmi2Discard;
}

fmi2Status fmi2GetRealStatus(fmi2Component c, const fmi2StatusKind s, fmi2Real *value)
{
    puts("fmi2GetRealStatus() - unused");
    return fmi2Discard;
}

fmi2Status fmi2GetIntegerStatus(fmi2Component c, const fmi2StatusKind s, fmi2Integer *value)
{
    puts("fmi2GetIntegerStatus() - unused");
    return fmi2Discard;
}

fmi2Status fmi2GetBooleanStatus(fmi2Component c, const fmi2StatusKind s, fmi2Boolean *value)
{
    puts("fmi2GetBooleanStatus() - unused");
    return fmi2Discard;
}

fmi2Status fmi2GetStringStatus(fmi2Component c, const fmi2StatusKind s, fmi2String *value)
{
    puts("fmi2GetStringStatus() - unused");
    return fmi2Discard;
}
